/**
 * Copyright 2012 Alfredo "Rainbowbreeze" Morresi
 * 
 * This file is part of Eureka! project.
 * 
 * Eureka! is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * Eureka! is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with Eureka!. If not, see http://www.gnu.org/licenses/.
 */
package it.rainbowbreeze.eureka.logic;

import it.rainbowbreeze.eureka.R;
import it.rainbowbreeze.eureka.common.LogFacility;
import it.rainbowbreeze.eureka.data.AppPreferencesDao;
import it.rainbowbreeze.eureka.domain.FilterCategories;
import it.rainbowbreeze.libs.helper.RainbowArrayHelper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;

/**
 * @author Alfredo "Rainbowbreeze" Morresi
 *
 */
public class FiltersManager {
    // ------------------------------------------ Private Fields
    private static final String LOG_HASH = FiltersManager.class.getSimpleName();
    private final LogFacility mLogFacility;
    private final AppPreferencesDao mAppPreferencesDao;
    
    private final static Map<FilterCategories, int[]> mCategoriesTree;
    private final static List<FilterCategories> mAllCategories; 
    static {
        mCategoriesTree = new HashMap<FilterCategories, int[]>();
        mCategoriesTree.put(FilterCategories.Economics, new int[]{7});
        mCategoriesTree.put(FilterCategories.Environment, new int[]{1, 2, 4});
        mCategoriesTree.put(FilterCategories.Social, new int[]{3, 5, 6});
        
        mAllCategories = new ArrayList<FilterCategories>();
        mAllCategories.add(FilterCategories.Economics);
        mAllCategories.add(FilterCategories.Environment);
        mAllCategories.add(FilterCategories.Social);
    }
    
    
    // -------------------------------------------- Constructors
    public FiltersManager(LogFacility logFacility, AppPreferencesDao appPreferencesDao) {
        mLogFacility = logFacility;
        mAppPreferencesDao = appPreferencesDao;
    }

    // --------------------------------------- Public Properties
    

    // ------------------------------------------ Public Methods
    public boolean isFilterCategoryActive(FilterCategories category) {
        int[] activeCategoryIds = mAppPreferencesDao.getCategoryIds();
        if (null == activeCategoryIds) return false;
        int categoryValueToSearch = FilterCategories.toInt(category);
        return RainbowArrayHelper.contains(categoryValueToSearch, activeCategoryIds);
    }
    
    public List<FilterStatus> loadFiltersStatuses(Context context, FilterCategories category) {
        List<FilterStatus> statuses = new ArrayList<FilterStatus>();
        int[] activeMeasureIds = mAppPreferencesDao.getMeasureIds();
        if (null == activeMeasureIds) return statuses;
        
        //based on category, maps the corresponding measure
        int[] measureIdsInCategory = mCategoriesTree.get(category);
        if (null == measureIdsInCategory) return statuses;
        
        //finds if measure ids are enable and their names
        for(int measureId : measureIdsInCategory) {
            String name = getMeasureIdName(context, measureId);
            boolean status = RainbowArrayHelper.contains(measureId, activeMeasureIds);
            statuses.add(new FilterStatus(name, status, measureId));
        }
        return statuses;
    }

    /**
     * Save filters configuration
     * @param activity
     * @param filterStatuses
     */
    public void saveFiltersStatuses(Context context, Map<FilterCategories, List<FilterStatus>> filterStatuses) {
        List<Integer> enabledFilters = new ArrayList<Integer>();
        for(Collection<FilterStatus> statuses : filterStatuses.values()) {
            if (null != statuses) {
                for (FilterStatus status : statuses) {
                    if (null != status) {
                        if (status.isEnabled) {
                            enabledFilters.add(status.measureId);
                        }
                    }
                }
            }
        }
        
        //now with all the enabled filters, save them
        int[] filtersToSave = new int[enabledFilters.size()];
        for (int i=0; i<enabledFilters.size(); i++) {
            filtersToSave[i] = enabledFilters.get(i).intValue();
        }
        mAppPreferencesDao.setMeasureIds(filtersToSave);
        mAppPreferencesDao.save();
    }

    /**
     * 
     * @param economicIsEnabled
     * @param environmentIsEnabled
     * @param socialIsEnabled
     */
    public void saveCategoriesStatuses(
            boolean economicIsEnabled,
            boolean environmentIsEnabled,
            boolean socialIsEnabled)
    {
        List<FilterCategories> categories = new ArrayList<FilterCategories>();
        
        if (economicIsEnabled) categories.add(FilterCategories.Economics);
        if (environmentIsEnabled) categories.add(FilterCategories.Environment);
        if (socialIsEnabled) categories.add(FilterCategories.Social);

        if (0 == categories.size()) {
            mAppPreferencesDao.setCategoryIds(null);
            
        } else {
            int[] values = new int[categories.size()];
            for(int i=0; i<categories.size(); i++) {
                values[i] = FilterCategories.toInt(categories.get(i));
            }
            mAppPreferencesDao.setCategoryIds(values);
        }
        mAppPreferencesDao.save();
    }
    
    /**
     * Returns only the active measure filters to use
     * @return
     */
    public int[] getActiveMeasureIdsFilters() {
        //get all the enabled measure ids
        int[] allMeasureIds = mAppPreferencesDao.getMeasureIds();
        List<Integer> measureIds = RainbowArrayHelper.convertToList(allMeasureIds);
        
        //for each disabled category, remove the corresponding measure filters
        for (FilterCategories category : mAllCategories) {
            if (!isFilterCategoryActive(category)) {
                int[] bannedMeasureIds = mCategoriesTree.get(category);
                for (int id : bannedMeasureIds) {
                    measureIds.remove(new Integer(id));
                }
            }
        }
        
        return RainbowArrayHelper.convertToArray(measureIds);
    }
    
    public boolean filtersArePresent() {
        int [] filters = getActiveMeasureIdsFilters();
        return (null != filters && filters.length > 0);
    }

    /**
     * 
     * @param arrayWhereRemove
     * @param arrayToRemove
     * @return
     */
    private int[] removeFromArray(int[] arrayWhereRemove, int[] arrayToRemove) {
        
        return null;
    }

    // ----------------------------------------- Private Methods
    /**
     * Given a category id, return its name
     * @param context
     * @param measureId
     * @return
     */
    private String getMeasureIdName(Context context, int measureId) {
        switch (measureId) {
        case 1:
            return context.getString(R.string.common_filter_1);
        case 2:
            return context.getString(R.string.common_filter_2);
        case 3:
            return context.getString(R.string.common_filter_3);
        case 4:
            return context.getString(R.string.common_filter_4);
        case 5:
            return context.getString(R.string.common_filter_5);
        case 6:
            return context.getString(R.string.common_filter_6);
        case 7:
            return context.getString(R.string.common_filter_7);
        default:
            return null;
        }
    }
    

    // ----------------------------------------- Private Classes
    /**
     * manage filters status
     */
    public static class FilterStatus {
        public final String filterName;
        public boolean isEnabled;
        public final int measureId;
        
        public FilterStatus(String filterName, boolean isEnabled, int measureId) {
            this.filterName = filterName;
            this.isEnabled = isEnabled;
            this.measureId = measureId;
        }
    }
}
